`include "defines.svh"
`include "axi_defines.svh"
`default_nettype none

module axi_arbiter(
    input  logic  clk,
    input  logic  reset,

    // Master 0 Interface
    input  data_t m0_debug_pc,
    input  logic  m0_awvalid,
    output logic  m0_awready,
    input  addr_t m0_awaddr,

    input  logic  m0_wvalid,
    output logic  m0_wready,
    input  data_t m0_wdata,
    input  strb_t m0_wstrb,

    output logic  m0_bvalid,
    input  logic  m0_bready,
    output resp_t m0_bresp,

    input  logic  m0_arvalid,
    output logic  m0_arready,
    input  addr_t m0_araddr,

    output logic  m0_rvalid,
    input  logic  m0_rready,
    output data_t m0_rdata,
    output resp_t m0_rresp,

    // Master 1 Interface
    input  data_t m1_debug_pc,
    input  logic  m1_awvalid,
    output logic  m1_awready,
    input  addr_t m1_awaddr,

    input  logic  m1_wvalid,
    output logic  m1_wready,
    input  data_t m1_wdata,
    input  strb_t m1_wstrb,

    output logic  m1_bvalid,
    input  logic  m1_bready,
    output resp_t m1_bresp,

    input  logic  m1_arvalid,
    output logic  m1_arready,
    input  addr_t m1_araddr,

    output logic  m1_rvalid,
    input  logic  m1_rready,
    output data_t m1_rdata,
    output resp_t m1_rresp,

    // Slave Interface
    output data_t s_debug_pc,
    output logic  s_awvalid,
    input  logic  s_awready,
    output addr_t s_awaddr,

    output logic  s_wvalid,
    input  logic  s_wready,
    output data_t s_wdata,
    output strb_t s_wstrb,

    input  logic  s_bvalid,
    output logic  s_bready,
    input  resp_t s_bresp,

    output logic  s_arvalid,
    input  logic  s_arready,
    output addr_t s_araddr,

    input  logic  s_rvalid,
    output logic  s_rready,
    input  data_t s_rdata,
    input  resp_t s_rresp
);




    //TODO:信号需要持续，直到master和slave交流完毕（r_shake置高）
    arb_state_t aw_state, ar_state;

    // Write Address Channel Arbiter
    always_ff @(posedge clk) begin
        if (reset) begin
            aw_state <= IDLE;
        end else begin
            case (aw_state)
                IDLE: begin
                    if (m1_awvalid) aw_state <= MASTER_1;
                    else if (m0_awvalid) aw_state <= MASTER_0;
                end
                MASTER_0: begin
                    if (s_bready && s_bvalid) aw_state <= IDLE;
                end
                MASTER_1: begin
                    if (s_bready && s_bvalid) aw_state <= IDLE;
                end
                default: begin
                    aw_state <= IDLE;
                end
            endcase
        end
    end
    // PC Arbiter
    assign s_debug_pc = (aw_state == MASTER_0 || ar_state == MASTER_0) ? m0_debug_pc :
                        (aw_state == MASTER_1 || ar_state == MASTER_1) ? m1_debug_pc : `NULL;


    // Write Address Channel Arbiter
    assign s_awvalid  = (aw_state == MASTER_0) ? m0_awvalid :
                        (aw_state == MASTER_1) ? m1_awvalid : `OFF;
    assign s_awaddr   = (aw_state == MASTER_0) ? m0_awaddr  :
                        (aw_state == MASTER_1) ? m1_awaddr  : `NULL;
    assign m0_awready = (aw_state == MASTER_0) ? s_awready  : `OFF;
    assign m1_awready = (aw_state == MASTER_1) ? s_awready  : `OFF;

    // Write Data Channel Arbiter
    assign s_wvalid  = (aw_state == MASTER_0) ? m0_wvalid :
                       (aw_state == MASTER_1) ? m1_wvalid : `OFF;
    assign s_wdata   = (aw_state == MASTER_0) ? m0_wdata  :
                       (aw_state == MASTER_1) ? m1_wdata  : `NULL;
    assign s_wstrb   = (aw_state == MASTER_0) ? m0_wstrb  :
                       (aw_state == MASTER_1) ? m1_wstrb  : `NULL;
    assign m0_wready = (aw_state == MASTER_0) ? s_wready  : `OFF;
    assign m1_wready = (aw_state == MASTER_1) ? s_wready  : `OFF;

    // Write Response Channel Arbiter
    assign m0_bvalid = (aw_state == MASTER_0) ? s_bvalid  : `OFF;
    assign m1_bvalid = (aw_state == MASTER_1) ? s_bvalid  : `OFF;
    assign m0_bresp  = (aw_state == MASTER_0) ? s_bresp   : `NULL;
    assign m1_bresp  = (aw_state == MASTER_1) ? s_bresp   : `NULL;
    assign s_bready  = (aw_state == MASTER_0) ? m0_bready :
                       (aw_state == MASTER_1) ? m1_bready : `OFF;

    // Read Address Channel Arbiter
    always_ff @(posedge clk) begin
        if (reset) begin
            ar_state <= IDLE;
        end else begin
            case (ar_state)
                IDLE: begin
                    if (m1_arvalid) ar_state <= MASTER_1;
                    else if (m0_arvalid) ar_state <= MASTER_0;
                end
                MASTER_0: begin
                    if (s_rready && s_rvalid) ar_state <= IDLE;
                end
                MASTER_1: begin
                    if (s_rready && s_rvalid) ar_state <= IDLE;
                end
                default: begin
                    ar_state <= IDLE;
                end
            endcase
        end
    end

    assign s_arvalid  = (ar_state == MASTER_0) ? m0_arvalid :
                        (ar_state == MASTER_1) ? m1_arvalid : `OFF;
    assign s_araddr   = (ar_state == MASTER_0) ? m0_araddr  :
                        (ar_state == MASTER_1) ? m1_araddr  : `NULL;
    assign m0_arready = (ar_state == MASTER_0) ? s_arready  : `OFF;
    assign m1_arready = (ar_state == MASTER_1) ? s_arready  : `OFF;

    // Read Data Channel Arbiter
    assign m0_rvalid = (ar_state == MASTER_0) ? s_rvalid  : `OFF;
    assign m1_rvalid = (ar_state == MASTER_1) ? s_rvalid  : `OFF;
    assign m0_rdata  = (ar_state == MASTER_0) ? s_rdata   : `NULL;
    assign m1_rdata  = (ar_state == MASTER_1) ? s_rdata   : `NULL;
    assign m0_rresp  = (ar_state == MASTER_0) ? s_rresp   : `NULL;
    assign m1_rresp  = (ar_state == MASTER_1) ? s_rresp   : `NULL;
    assign s_rready  = (ar_state == MASTER_0) ? m0_rready :
                       (ar_state == MASTER_1) ? m1_rready : `OFF;

endmodule
